//var 声明  var声明可以在包含它的函数，模块，命名空间或全局作用域内部任何位置被访问
var a = 1;

function f() {
    var a = 10;
    return function g() {
        var b = a + 1;
        return b;
    };
}

var g = f();
g(); // returns 11;

for (var i = 0; i < 10; i++) {
    setTimeout(function () {
        console.log("var声明：" + i);
    }, 100 * i);
}
// 打印出10个10，因为var没有块级作用域，i在for循环结束后才被销毁，所以10个定时器都访问的是同一个i

for (var i = 0; i < 10; i++) {
    (function (i) {
        setTimeout(function () {
            console.log("var声明 + 立即执行函数：" + i);
        }, 100 * i);
    })(i);
}
// 打印出0到9，因为每次循环都会创建一个新的立即执行函数，每个立即执行函数都有自己的i，所以不会互相影响

//let 声明
//块作用域 let声明的变量仅在声明所在的块级作用域内有效,块级作用域的变量的另一个特点是，它们不能在被声明之前读或写。
for (let i = 0; i < 10; i++) {
    setTimeout(function () {
        console.log("let声明：", i);
    }, 100 * i);
}
// 打印出0到9，因为let有块级作用域，每次循环都会创建一个新的i，所以不会互相影响

//const 声明
//const 声明创建一个常量，其值不能通过重新赋值来改变，也不能重新声明。
const numLivesForCat = 9;
const kitty = {
    name: "Aurora",
    numLives: numLivesForCat,
};
//kitty = "Cat"; // Error
kitty.name = "Kitty"; // OK

//解构数组
let input = [1, 2];
let [first, second] = input;
console.log(first); // outputs 1
console.log(second); // outputs 2

let [third, , , fourth] = [1, 2, 3, 4];
console.log(third); // outputs 1
console.log(fourth); // outputs 4

//解构对象
let o = {
    a: "foo",
    b: 12,
    c: "bar",
};
let { a: newA, b = 0 } = o; //属性重命名a: newA ;b = 0设置默认值
console.log(newA); // outputs "foo"
console.log(b); // outputs 12

//默认值
function f3({ a = 0, b = 0 } = {}) {
    console.log(a, b);
}

//解构函数参数
function f4({ a, b = 0 } = { a: "" }): void {
    // ...
}
f4({ a: "yes" }); // ok, default b = 0
f4(); // ok, default to {a: ""}, which then defaults b = 0
// f4({}); // error, 'a' is required if you supply an argument

//展开运算符
let first1 = [1, 2];
let second1 = [3, 4];
let bothPlus = [0, ...first1, ...second1];
console.log(bothPlus); // outputs [0, 1, 2, 3, 4]
//展开对象
let obj1 = { a: 1, b: 2, c: 3 };
let copy = { ...obj1 };
console.log(copy); // outputs { a: 1, b: 2, c: 3 }
